package easycloud.ecs.common.util;

import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import easycloud.ecs.provider.model.IStorageObject;

public class Md5Utils {
	/**
	 * Computes the MD5 hash of the given data and returns it as an array of
	 * bytes.
	 */
	public static byte[] computeMD5Hash(byte[] data)
			throws NoSuchAlgorithmException, IOException {
		return Md5Utils.computeMD5Hash(new ByteArrayInputStream(data));
	}

	public static String computeMD5Hash(File file) {
		String result = "";
		try {
			byte[] md5Hash = Md5Utils.computeMD5Hash(new FileInputStream(file));
			result = BinaryUtils.toBase64(md5Hash);
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return result;
	}

	/**
	 * Computes the MD5 hash of the data in the given input stream and returns
	 * it as an array of bytes.
	 */
	public static byte[] computeMD5Hash(InputStream is)
			throws NoSuchAlgorithmException, IOException {
		BufferedInputStream bis = new BufferedInputStream(is);
		try {
			MessageDigest messageDigest = MessageDigest.getInstance("MD5");
			byte[] buffer = new byte[16384];
			int bytesRead = -1;
			while ((bytesRead = bis.read(buffer, 0, buffer.length)) != -1) {
				messageDigest.update(buffer, 0, bytesRead);
			}
			return messageDigest.digest();
		} finally {
			try {
				bis.close();
			} catch (Exception e) {
				System.err
						.println("Unable to close input stream of hash candidate: "
								+ e);
			}
		}
	}

	public static String computeMD5Hash(IStorageObject object) {
		String result = "";
		try {
			byte[] md5Hash = Md5Utils.computeMD5Hash(object.getObjectContent());
			result = BinaryUtils.toBase64(md5Hash);
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return result;
	}
}
